﻿using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.Guids;
using Volo.Abp.Modularity;
using Volo.Abp.Testing;
using Volo.Abp.Uow;
using Xunit.Abstractions;

namespace FlyingEye.ApplicationTests
{
    public class MonitorServiceTestBase<TStartupModule> : AbpIntegratedTest<TStartupModule> where TStartupModule : IAbpModule
    {
        protected Volo.Abp.ObjectMapping.IObjectMapper ObjectMapper { get; }

        protected ITestOutputHelper Output { get; }

        protected IGuidGenerator GuidGenerator { get; }

        public MonitorServiceTestBase(ITestOutputHelper testOutputHelper)
        {
            ObjectMapper = GetRequiredService<Volo.Abp.ObjectMapping.IObjectMapper>();
            GuidGenerator = GetRequiredService<IGuidGenerator>();
            Output = testOutputHelper;
        }

        protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
        {
            var currentDir = Path.GetDirectoryName(GetType().Assembly.Location) ?? throw new InvalidOperationException("程序集路基错误。");
            var baseDir = Path.Combine(currentDir, "../../../../", "FlyingEye.MonitorService");
            var info = new DirectoryInfo(baseDir);

            options.Configuration.BasePath = info.FullName;
            options.Configuration.EnvironmentName = "Development";

            options.UseAutofac();
        }

        protected virtual Task WithUnitOfWorkAsync(Func<Task> func)
        {
            return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func);
        }

        protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func<Task> action)
        {
            using (var scope = ServiceProvider.CreateScope())
            {
                var uowManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();

                using (var uow = uowManager.Begin(options))
                {
                    await action();

                    await uow.CompleteAsync();
                }
            }
        }

        protected virtual Task<TResult> WithUnitOfWorkAsync<TResult>(Func<Task<TResult>> func)
        {
            return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func);
        }

        protected virtual async Task<TResult> WithUnitOfWorkAsync<TResult>(AbpUnitOfWorkOptions options, Func<Task<TResult>> func)
        {
            using (var scope = ServiceProvider.CreateScope())
            {
                var uowManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();

                using (var uow = uowManager.Begin(options))
                {
                    var result = await func();
                    await uow.CompleteAsync();
                    return result;
                }
            }
        }
    }
}
